package com.gitee.wsl.prism4j.languages

import com.gitee.wsl.prism4j.GrammarUtils
import com.gitee.wsl.prism4j.GrammarUtils.require
import com.gitee.wsl.prism4j.Prism4j
import com.gitee.wsl.prism4j.Prism4j.Companion.pattern
import com.gitee.wsl.prism4j.Prism4j.Companion.token
import com.gitee.wsl.prism4j.annotations.Extend
import com.gitee.wsl.prism4j.Prism4j.Pattern

@Suppress("unused")
@Extend("clike")
object Prism_go {
    fun create(prism4j: Prism4j): Prism4j.Grammar {
        val go: Prism4j.Grammar = GrammarUtils.extend(
            require(prism4j, "clike"),
            "go", GrammarUtils.TokenFilter { token: Prism4j.Token? -> "class-name" != token!!.name() },
            token(
                "keyword",
                pattern(Pattern.compile("\\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\\b"))
            ),
            token("boolean", pattern(Pattern.compile("\\b(?:_|iota|nil|true|false)\\b"))),
            token(
                "operator",
                pattern(Pattern.compile("[*\\/%^!=]=?|\\+[=+]?|-[=-]?|\\|[=|]?|&(?:=|&|\\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\\.\\.\\."))
            ),
            token(
                "number",
                pattern(
                    Pattern.compile(
                        "(?:\\b0x[a-f\\d]+|(?:\\b\\d+\\.?\\d*|\\B\\.\\d+)(?:e[-+]?\\d+)?)i?",
                        Pattern.CASE_INSENSITIVE
                    )
                )
            ),
            token("string", pattern(Pattern.compile("([\"'`])(\\\\[\\s\\S]|(?!\\1)[^\\\\])*\\1"), false, true))
        )

        // clike doesn't have builtin
        GrammarUtils.insertBeforeToken(
            go, "boolean",
            token(
                "builtin",
                pattern(Pattern.compile("\\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\\b"))
            )
        )

        return go
    }
}
